import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class CartModel {
  final bool selected;
  final String goodsName;
  final String subTitle;
  final double price;
  final int num;
  final String goodStoreName;

  const CartModel(this.selected, this.goodsName, this.subTitle, this.price,
      this.num, this.goodStoreName);

  static CartModel copy(CartModel m) {
    return new CartModel(m.selected, m.goodStoreName, m.subTitle, m.price,
        m.num, m.goodStoreName);
  }

  String toJson() {
    return """
    {
      "selected" : ${selected},
      "goodsName" : "${goodsName}",
      "subTitle" : "${subTitle}",
      "price" : ${price},
      "num" : ${num},
      "goodStoreName" : "${goodStoreName}"
    }
    """;
  }

  static CartModel convertToModel(String str) {
    Map<String, dynamic> map = json.decode(str);
    return CartModel(map["selected"], map["goodsName"], map["subTitle"],
        map["price"], map["num"], map["goodStoreName"]);
  }

  @override
  String toString() {
    return 'CartModel{selected: $selected, goodsName: $goodsName, subTitle: $subTitle, price: $price, num: $num, goodStoreName: $goodStoreName}';
  }
}

class YouPinCartPage extends StatefulWidget {
  @override
  _YouPinCartPageState createState() => _YouPinCartPageState();
}

class _YouPinCartPageState extends State<YouPinCartPage> {
  bool _allFlag = false;

  double _amount = 0.0;

  var _list = <CartModel>[
    CartModel(false, "悦米机械键盘104键 Cherry轴", "比加入时降低￥30.00", 299.00, 1, "有品甄选"),
    CartModel(false, "贝瓦积木小火车玲珑系", "", 109.00, 1, "有品甄选"),
    CartModel(false, "小米笔记本Pro 15.6 GTX版 I7 16G", "", 7599.00, 1, "小米自营"),
  ];

  @override
  void initState() {
    super.initState();
    getCache();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title:
            Text("购物车", style: TextStyle(color: Colors.black, fontSize: 18.0)),
        centerTitle: true,
        backgroundColor: Colors.white,
        elevation: 0.5,
        actions: <Widget>[
          IconButton(
            onPressed: _editHandler,
            icon: Text("编辑",
                style: TextStyle(fontSize: 14.0, color: Colors.black)),
          )
        ],
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            Expanded(
              child: ListView.builder(
                itemBuilder: (context, index) => CartItemWidget(
                      padding:
                          EdgeInsets.only(right: 10.0, top: 10.0, bottom: 10.0),
                      model: _list[index],
                      onTap: () => changeCount(
                          index,
                          (m) => CartModel(!m.selected, m.goodsName, m.subTitle,
                              m.price, m.num, m.goodStoreName)),
                      incrementCallBack: () => _incrementCallBack(index),
                      decrementCallBack: () => _decrementCallBack(index),
                    ),
                itemCount: _list.length,
                itemExtent: 90.0,
              ),
            ),
            Container(
              height: 55.0,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  const Divider(height: 1.0),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: <Widget>[
                      _allFlagText("全选"),
                      _settlementWidget(),
                    ],
                  )
                ],
              ),
            )
          ],
        ),
      ),
    );
  }

  Future<void> saveState() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setBool("_allFlag", _allFlag);
    await prefs.setStringList("list", _list.map((i) => i.toJson()).toList());
  }

  void getCache() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    final List<String> list = prefs.getStringList("list");
    final _flag = prefs.getBool("_allFlag");
    if (list != null) {
      final List<CartModel> _newList =
          list.map((m) => CartModel.convertToModel(m)).toList();
      double amount = _computeList(_newList);
      setState(() {
        _list = _newList;
        _amount = amount;
        _allFlag = _flag;
      });
    }
  }

  void _editHandler() {}

  void _allFlagTap() async {
    var _newList = _list
        .map((m) => CartModel(!_allFlag, m.goodsName, m.subTitle, m.price,
            m.num, m.goodStoreName))
        .toList();
    final amount = _computeList(_newList);
    setState(() {
      _allFlag = !_allFlag;
      _list = _newList;
      _amount = amount;
    });
    await saveState();
  }

  Widget _allFlagText(String title) {
    final widget = _allFlag
        ? IconButton(
            icon: Icon(Icons.check_circle, color: Colors.red[700]),
            onPressed: _allFlagTap,
          )
        : IconButton(
            icon: Icon(Icons.panorama_fish_eye, color: Colors.grey),
            onPressed: _allFlagTap,
          );
    return Row(
      children: <Widget>[widget, Text(title, style: TextStyle(fontSize: 13.0))],
    );
  }

  Widget _settlementWidget() {
    return Row(
      children: <Widget>[
        Text("合计: ", style: TextStyle(fontSize: 13.0)),
        Text("￥${_amount}",
            style: TextStyle(fontSize: 13.0, color: Colors.red[800])),
        const SizedBox(width: 5.0),
        Container(
          height: 54.0,
          child: FlatButton(
            onPressed: () {},
            color: Colors.red[700],
            shape: RoundedRectangleBorder(),
            child: Text("去结算", style: TextStyle(color: Colors.white)),
          ),
        )
      ],
    );
  }

  _incrementCallBack(int index) async {
    changeCount(
        index,
        (item) => CartModel(item.selected, item.goodsName, item.subTitle,
            item.price, item.num + 1, item.goodStoreName));
    await saveState();
  }

  _decrementCallBack(int index) async {
    changeCount(
        index,
        (m) => CartModel(m.selected, m.goodsName, m.subTitle, m.price,
            m.num - 1, m.goodStoreName));
    await saveState();
  }

  changeCount(int index, CartModel f(CartModel e)) async {
    List<CartModel> _newList = [];
    int _selected = 0;
    for (int i = 0; i < _list.length; i++) {
      var item = _list[i];
      if (i == index) {
        var item0 = f(item);
        if (item0.num == 0) {
          return;
        }
        if (item0.selected) _selected += 1;
        _newList.add(item0);
      } else {
        if (item.selected) _selected += 1;
        _newList.add(CartModel(item.selected, item.goodsName, item.subTitle,
            item.price, item.num, item.goodStoreName));
      }
    }

    print("_allFlag: ${_allFlag}");
    print("_selected num: ${_selected}, list len: ${_list.length}");
    final amount = _computeList(_newList);
    setState(() {
      _list = _newList;
      _amount = amount;
      if (!_allFlag && _selected == _list.length) {
        _allFlag = true;
      } else if (_allFlag && _selected == _list.length) {
        _allFlag = true;
      } else {
        _allFlag = false;
      }
    });

    await saveState();
  }

  double _computeList(List<CartModel> newList) {
    return newList
        .where((i) => i.selected)
        .map((i) => (i.price * i.num))
        .fold(0.0, (a, b) => a + b);
  }
}

class CartItemWidget extends StatelessWidget {
  final CartModel model;
  final VoidCallback onTap;
  final EdgeInsetsGeometry padding;
  final VoidCallback incrementCallBack;
  final VoidCallback decrementCallBack;

  const CartItemWidget(
      {this.model,
      this.onTap,
      this.padding,
      this.incrementCallBack,
      this.decrementCallBack});

  @override
  Widget build(BuildContext context) {
    final selectedWidget = model.selected
        ? IconButton(
            icon: Icon(Icons.check_circle, color: Colors.red[700]),
            onPressed: onTap,
          )
        : IconButton(
            icon: Icon(Icons.panorama_fish_eye, color: Colors.grey),
            onPressed: onTap,
          );
    return Padding(
      padding: padding,
      child: Row(
        children: <Widget>[
          selectedWidget,
          Container(
            width: 90.0,
            height: 90.0,
            decoration: BoxDecoration(
              color: Colors.grey[300],
              borderRadius: BorderRadius.circular(3.0),
            ),
          ),
          const SizedBox(width: 10.0),
          Expanded(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Text(model.goodsName, maxLines: 2),
                    model.subTitle.isNotEmpty
                        ? Text(
                            model.subTitle,
                            style: TextStyle(
                                fontSize: 13.0, color: Colors.red[800]),
                          )
                        : Container(width: 0.0, height: 0.0),
                  ],
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    Text("￥${model.price}",
                        style:
                            TextStyle(color: Colors.red[800], fontSize: 15.0)),
                    IncrementWidget(
                      num: model.num,
                      incrementCallBack: incrementCallBack,
                      decrementCallBack: decrementCallBack,
                    ),
                  ],
                ),
              ],
            ),
          )
        ],
      ),
    );
  }
}

class IncrementWidget extends StatelessWidget {
  final int num;
  final VoidCallback incrementCallBack;
  final VoidCallback decrementCallBack;

  const IncrementWidget(
      {this.num, this.incrementCallBack, this.decrementCallBack});

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTap: decrementCallBack,
          child: _widget(Icon(Icons.remove, size: 14.0), false),
        ),
        _widget(Text("$num", style: TextStyle(fontSize: 13.0)), true),
        GestureDetector(
          behavior: HitTestBehavior.opaque,
          onTap: incrementCallBack,
          child: _widget(Icon(Icons.add, size: 14.0), false),
        ),
      ],
    );
  }

  Widget _widget(Widget w, bool centerFlag) {
    return Container(
      width: 35.0,
      height: 25.0,
      alignment: Alignment.center,
      decoration: BoxDecoration(
          border: Border(
        top: const BorderSide(color: Colors.grey, width: 1.0),
        bottom: const BorderSide(color: Colors.grey, width: 1.0),
        left: BorderSide(color: Colors.grey, width: centerFlag ? 0.0 : 1.0),
        right: BorderSide(color: Colors.grey, width: centerFlag ? 0.0 : 1.0),
      )),
      child: w,
    );
  }
}
